#include <netinet/in.h>
#include <string.h>
#include <iostream>
#include <sstream>

#include "client.hpp"
///////////////////////////////////////////////////////////////////////////////////////////////////

rudpClient :: rudpClient() : rudp()
{
}

rudpClient :: rudpClient( const std::string& url , int port ): rudp( url , port )
{
	
}

rudpClient :: ~rudpClient()
{
	if( multi_pk_buf.size() > 0 )
		multi_pk_buf.clear();
}


void rudpClient :: close()
{
	delete this;
}


void rudpClient :: do_on_close_echo( rudp_pkge_t * pkge , const struct sockaddr * peer )
{
	if( pkge ){
		delete this;
	}
}

void rudpClient :: do_on_close( rudp_pkge_t * pkge , const struct sockaddr * peer )
{
	if( pkge ){
		rudp_pkge_t * pkg = nullptr;
		packet_close_e( pkge , &pkg );
		if( pkg )
			send_packet( pkg );
		delete this;
	}
}

void rudpClient :: do_on_connect_echo( rudp_pkge_t * pkge , const struct sockaddr * peer )
{
	if( pkge == nullptr ) return;
	rudp_pkge_t * pkg = nullptr;
	packet_connect_e( pkge , &pkg );
	
	if( pkg )
		send_packet( pkg );

	if( connect_cb )
		connect_cb( m_error );
}

void rudpClient :: do_on_connect( rudp_pkge_t * pkge , const struct sockaddr * add )
{
	// do nothing for client
}


void rudpClient :: do_on_send( rudp_pkge_t * pkge , const struct sockaddr * add )
{
	if( pkge == nullptr ) return;

	// 发送响应
	rudp_pkge_t * pkg = nullptr;
	packet_e( pkge , &pkg );
	send_packet( pkg );
	// 检查数据包是否是多包结构
	if( pkge->pkg_count > 1 ){
		if( multi_pk_buf.count == 0 ){
			multi_pk_buf.count = pkge->pkg_count;
		}
		if( multi_pk_buf.size() < multi_pk_buf.count )
			multi_pk_buf.insert( pkge );
		else{
			char * data;
			int l = multi_pk_buf.get( &data );
			// TODO : 是否要添加其他的处理内容？
			if( l > 0 && data && recv_cb ){
				recv_cb( data , l , m_error );
			}
		}
		
	}else if( recv_cb ){
	      recv_cb( ( const char *)(pkg->data) , pkg->len , m_error );
	}
}

void rudpClient :: Connect( const std::string& url , int port )
{
	rudp::connect( url , port );
}

void rudpClient :: Connect( const std::string& url , int port , std::function< void ( rudp::err_code ) > fun )
{
	connect( url , port , fun );
}

rudp::err_code rudpClient :: Close()
{
	close();

	return m_error;
}

rudp::err_code rudpClient :: evtClose( std::function< void (rudp::err_code ) > fun )
{
	return evt_close( fun );
}


rudp::err_code rudpClient :: evtConnected( std::function< void ( rudp::err_code ) > fun )
{
	return evt_connected( fun );
}

rudp::err_code rudpClient :: Send( const char * data , size_t len )
{
	return send( data , len );
}

void rudpClient :: evtSend( std::function< void (rudp::err_code) > fun )
{
	onsend( fun );
}

rudp :: err_code rudpClient :: evtRecv( std::function< void ( const char * , size_t , rudp::err_code )> fun )
{
	return evt_recv( fun );
}
